
using System;
using System.Reflection;
using System.Windows.Forms;

using Derm.Render;
using Derm.Scene;
using Derm.Xml.Collada;

namespace Derm.Examples
{
	class ExamplePipeline : RenderPipeline
	{
		#region Constructors
		
		/// <summary>
		/// ExamplePipeline constructor. 
		/// </summary>
		/// <param name="rSurface">
		/// A <see cref="RenderSurface"/> where the pipeline is executed on.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// This exception is thrown if the parameter <paramref name="rSurface"/> is null.
		/// </exception>
		public ExamplePipeline(RenderSurface rSurface) : base(rSurface)
		{
			RenderWindow window = (RenderWindow) Surface;

			window.NestedForm.MouseClick += RenderWindow_MouseClick;
			window.NestedForm.MouseUp += RenderWindow_MouseUp;
			window.NestedForm.MouseDown += RenderWindow_MouseDown;
			window.NestedForm.MouseMove += RenderWindow_MouseMove;
		}

		void RenderWindow_MouseMove(object sender, MouseEventArgs e)
		{
			RenderGraphNode node = mScene.Hierarchy.FindNode(delegate(RenderGraphNode graphNode)
          	{
				if ((graphNode.Identifier == "plane") || (graphNode.Identifier == "Box") || (graphNode.Identifier == "LOD3sp") || (graphNode.Identifier == "Scene_Root")) {
					return (true);
				} else
					return (false);
          	});

			if (node != null) {
				node.LocalModel.Rotate(new Quaternion(Vertex3f.UnitY, -1.0f));
				//node.LocalModel.Rotate(new Quaternion(Vertex3f.UnitZ, +2.0f));
			}
		}

		void RenderWindow_MouseDown(object sender, MouseEventArgs e)
		{
			
		}

		void RenderWindow_MouseUp(object sender, MouseEventArgs e)
		{
			
		}

		void RenderWindow_MouseClick(object sender, MouseEventArgs e)
		{
			
		}
		
		#endregion

		#region Example Switching

		public void SetExample(string exampleName)
		{
			mCurrentInitialize = GetExampleInitialize(exampleName);
			mCurrentReset = GetExampleReset(exampleName);
			mCurrentExec = GetExampleExec(exampleName);

			// Store example name
			mExampleName = exampleName;
		}

		MethodInfo GetExampleInitialize(string name)
		{
			return (GetType().GetMethod("Initialize" + name, BindingFlags.Instance | BindingFlags.NonPublic));
		}

		MethodInfo GetExampleReset(string name)
		{
			return (GetType().GetMethod("Reset" + name, BindingFlags.Instance | BindingFlags.NonPublic));
		}

		MethodInfo GetExampleExec(string name)
		{
			return (GetType().GetMethod("Exec" + name, BindingFlags.Instance | BindingFlags.NonPublic));
		}

		/// <summary>
		/// Current example.
		/// </summary>
		private string mExampleName = null;

		#endregion

		#region Colored UnitCube Example

		private void InitializeColoredUnitCube(RenderContext ctx)
		{
			// cube_triangulate.dae
			// collada.dae
			// sphere_triangulate.dae
			// sevenListo2.dae
			// seymourplane_triangulate.dae
			// duck_triangulate.dae
			// diningroomC.dae
			// BikeFromXSI.dae

			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Cube/cube_triangulate.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Multimaterial/multimtl_triangulate.dae");
			ColladaDocument colladaDocument = ColladaDocument.Load("Data/Duck/duck_triangulate.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Duck/duck.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/BikeFromXSI/BikeFromXSI.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Dice/dice.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Seymour Plane/seymourplane_triangulate.dae");
			//ColladaDocument colladaDocument = ColladaDocument.Load("Data/Collada Logo/collada.dae");

			// diningroomC.dae

			mScene = colladaDocument.Create();
			mScene.Create(ctx);
			mScene.SelectFirstCamera();

			mFpsText = new FontObject("San Serif", 16, FontStyle.None);
			mFpsText.Create(ctx);
		}

		private void ResetColoredUnitCube(RenderContext ctx)
		{
			
		}

		private void ExecColoredUnitCube(RenderContext ctx)
		{
			Surface.SetClearColor(new ColorRGBAF(0.1f, 0.3f, 0.1f, 1.0f));
			Surface.Clear(ctx);

			mScene.Render(ctx);
		}

		private FontObject mFpsText;

		private RenderScene mScene;

		#endregion

		#region RenderPipeline Overrides

		public override void InitializePipeline(RenderContext ctx)
		{
			mCurrentInitialize.Invoke(this, new object[]{ ctx });
		}

		protected override void ResetThisPipeline(RenderContext ctx)
		{
			mCurrentReset.Invoke(this, new object[]{ ctx });
		}

		protected override void ExecThisPipeline(RenderContext ctx)
		{
			mCurrentExec.Invoke(this, new object[]{ ctx });
		}

		private MethodInfo mCurrentInitialize = null;

		private MethodInfo mCurrentReset = null;

		private MethodInfo mCurrentExec = null;

		private MethodInfo mCurrentTerminate = null;

		#endregion
	}
}
